diff --git a/admin/cron.php b/admin/cron.php
index 79def22..9555309 100644
--- a/admin/cron.php
+++ b/admin/cron.php
@@ -125,6 +125,10 @@
     get_mailer('close');
     mtrace("Finished activity modules");
 
+    //now do plagiarism checks
+    require_once($CFG->libdir.'/plagiarismlib.php');
+    plagiarism_cron();
+
     mtrace("Starting blocks");
     if ($blocks = $DB->get_records_select("block", "cron > 0 AND ((? - lastcron) > cron) AND visible = 1", array($timenow))) {
         // we will need the base class.
diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php
index 156c972..820b79a 100644
--- a/admin/settings/plugins.php
+++ b/admin/settings/plugins.php
@@ -386,7 +386,17 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext))
         }
     }
 }
-
+if ($hassiteconfig && !empty($CFG->enableplagiarism)) {
+    $ADMIN->add('modules', new admin_category('plagiarism', get_string('plagiarism', 'plagiarism')));
+    $temp = new admin_settingpage('plagiarismsettings', get_string('plagiarismsettings', 'plagiarism'));
+    $temp->add(new admin_setting_manageplagiarism());
+    $ADMIN->add('plagiarism', $temp);
+    foreach (get_plugin_list('plagiarism') as $plugin => $plugindir) {
+        if (file_exists($plugindir.'/settings.php')) {
+            $ADMIN->add('plagiarism', new admin_externalpage('plagiarism'.$plugin, get_string($plugin, 'plagiarism_'.$plugin), "$CFG->wwwroot/plagiarism/$plugin/settings.php", 'moodle/site:config'));
+        }
+    }
+}
 $ADMIN->add('reports', new admin_externalpage('comments', get_string('comments'), $CFG->wwwroot.'/comment/', 'moodle/site:viewreports'));
 /// Now add reports
 
diff --git a/admin/settings/subsystems.php b/admin/settings/subsystems.php
index e30f07a..7998f47 100644
--- a/admin/settings/subsystems.php
+++ b/admin/settings/subsystems.php
@@ -39,4 +39,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
     $optionalsubsystems->add(new admin_setting_configcheckbox('enableavailability',
         get_string('enableavailability','condition'),
         get_string('configenableavailability','condition'), 0));
+
+    $optionalsubsystems->add(new admin_setting_configcheckbox('enableplagiarism', get_string('enableplagiarism','plagiarism'), get_string('configenableplagiarism','plagiarism'), 0));
 }
diff --git a/course/modedit.php b/course/modedit.php
index e1bf014..f55a4a5 100644
--- a/course/modedit.php
+++ b/course/modedit.php
@@ -29,6 +29,7 @@ require_once($CFG->libdir.'/filelib.php');
 require_once($CFG->libdir.'/gradelib.php');
 require_once($CFG->libdir.'/completionlib.php');
 require_once($CFG->libdir.'/conditionlib.php');
+require_once($CFG->libdir.'/plagiarismlib.php');
 
 $add    = optional_param('add', '', PARAM_ALPHA);     // module name
 $update = optional_param('update', 0, PARAM_INT);
@@ -556,6 +557,7 @@ if ($mform->is_cancelled()) {
 
     rebuild_course_cache($course->id);
     grade_regrade_final_grades($course->id);
+    plagiarism_save_form_elements($fromform); //save plagiarism settings
 
     if (isset($fromform->submitbutton)) {
         redirect("$CFG->wwwroot/mod/$module->name/view.php?id=$fromform->coursemodule");
diff --git a/lang/en/plagiarism.php b/lang/en/plagiarism.php
new file mode 100644
index 0000000..1acc769
--- /dev/null
+++ b/lang/en/plagiarism.php
@@ -0,0 +1,9 @@
+<?php
+$string['availableplugins'] = 'Available plugins';
+$string['configplagiarismplugins'] = 'Please choose the plagiarism plugin you would like to configure';
+$string['enableplagiarism'] ='Enable plagiarism plugins';
+$string['configenableplagiarism'] = 'This will allow administrators to configure plagiarism plugins (if installed)';
+$string['manageplagiarism'] = 'Manage plagiarism plugins';
+$string['nopluginsinstalled'] = 'No plagiarism plugins are installed.';
+$string['plagiarism'] = 'Plagiarism prevention';
+$string['plagiarismsettings'] = 'Plagiarism settings';
diff --git a/lib/adminlib.php b/lib/adminlib.php
index e13cf50..4215e0e 100644
--- a/lib/adminlib.php
+++ b/lib/adminlib.php
@@ -6735,6 +6735,92 @@ class admin_setting_manageexternalservices extends admin_setting {
         return highlight($query, $return);
     }
 }
+/**
+ * Special class for plagiarism administration.
+ *
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class admin_setting_manageplagiarism extends admin_setting {
+/**
+ * Calls parent::__construct with specific arguments
+ */
+    public function __construct() {
+        $this->nosave = true;
+        parent::__construct('plagiarismui', get_string('plagiarismsettings', 'plagiarism'), '', '');
+    }
+
+    /**
+     * Always returns true
+     *
+     * @return true
+     */
+    public function get_setting() {
+        return true;
+    }
+
+    /**
+     * Always returns true
+     *
+     * @return true
+     */
+    public function get_defaultsetting() {
+        return true;
+    }
+
+    /**
+     * Always returns '' and doesn't write anything
+     *
+     * @return string Always returns ''
+     */
+    public function write_setting($data) {
+    // do not write any setting
+        return '';
+    }
+
+    /**
+     * Return XHTML to display control
+     *
+     * @param mixed $data Unused
+     * @param string $query
+     * @return string highlight
+     */
+    public function output_html($data, $query='') {
+        global $CFG, $OUTPUT;
+
+        // display strings
+        $txt = get_strings(array('settings', 'name'));
+
+        $plagiarismplugins = get_plugin_list('plagiarism');
+        if (empty($plagiarismplugins)) {
+            return get_string('nopluginsinstalled', 'plagiarism');
+        }
+
+        $return = $OUTPUT->heading(get_string('availableplugins', 'plagiarism'), 3, 'main');
+        $return .= $OUTPUT->box_start('generalbox authsui');
+
+        $table = new html_table();
+        $table->head  = array($txt->name, $txt->settings);
+        $table->align = array('left', 'center');
+        $table->data  = array();
+        $table->attributes['class'] = 'manageplagiarismtable generaltable';
+
+        // iterate through auth plugins and add to the display table
+        $authcount = count($plagiarismplugins);
+        foreach ($plagiarismplugins as $plugin => $dir) {
+            if (file_exists($dir.'/settings.php')) {
+                $displayname = "<span>".get_string($plugin, 'plagiarism_'.$plugin)."</span>";
+                // settings link
+                $settings = "<a href=\"$CFG->wwwroot/plagiarism/$plugin/settings.php\">{$txt->settings}</a>";
+                // add a row to the table
+                $table->data[] =array($displayname, $settings);
+            }
+        }
+        $return .= html_writer::table($table);
+        $return .= get_string('configplagiarismplugins', 'plagiarism');
+        $return .= $OUTPUT->box_end();
+        return highlight($query, $return);
+    }
+}
 
 /**
  * Special class for overview of external services
diff --git a/lib/moodlelib.php b/lib/moodlelib.php
index 62bc6a7..820468b 100644
--- a/lib/moodlelib.php
+++ b/lib/moodlelib.php
@@ -6940,6 +6940,7 @@ function get_core_subsystems() {
             'notes'       => 'notes',
             'pagetype'    => NULL,
             'pix'         => NULL,
+            'plagiarism'  => 'plagiarism',
             'portfolio'   => 'portfolio',
             'publish'     => 'course/publish',
             'question'    => 'question',
@@ -6994,6 +6995,7 @@ function get_plugin_types($fullpaths=true) {
                       'portfolio'     => 'portfolio',
                       'qtype'         => 'question/type',
                       'qformat'       => 'question/format',
+                      'plagiarism'    => 'plagiarism',
                       'theme'         => 'theme'); // this is a bit hacky, themes may be in dataroot too
 
         $mods = get_plugin_list('mod');
diff --git a/lib/plagiarismlib.php b/lib/plagiarismlib.php
new file mode 100644
index 0000000..b8c8546
--- /dev/null
+++ b/lib/plagiarismlib.php
@@ -0,0 +1,170 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * plagiarismlib.php - Contains core Plagiarism related functions.
+ *
+ * @since 2.0
+ * @package    moodlecore
+ * @subpackage plagiarism
+ * @copyright  2010 Dan Marsden http://danmarsden.com
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+///// GENERIC PLAGIARISM FUNCTIONS ////////////////////////////////////////////////////
+
+if (!defined('MOODLE_INTERNAL')) {
+    die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
+}
+
+/**
+ * displays the similarity score and provides a link to the full report if allowed.
+ *
+ * @param object  $linkarray contains all relevant information for the plugin to generate a link
+ * @return string - url to allow login/viewing of a similarity report
+ */
+function plagiarism_get_links($linkarray) {
+    global $CFG;
+    if (empty($CFG->enableplagiarism)) {
+        return '';
+    }
+    $plagiarismplugins = plagiarism_load_available_plugins();
+    $output = '';
+    foreach($plagiarismplugins as $plugin => $dir) {
+        require_once($dir.'/lib.php');
+        $plagiarismclass = "plagiarism_plugin_$plugin";
+        $plagiarismplugin = new $plagiarismclass;
+        $output .= $plagiarismplugin->get_links($linkarray);
+    }
+    return $output;
+}
+
+/**
+ * saves/updates plagiarism settings from a modules config page - called by course/modedit.php
+ *
+ * @param object $data - form data
+ */
+function plagiarism_save_form_elements($data) {
+    global $CFG;
+    if (empty($CFG->enableplagiarism)) {
+        return '';
+    }
+    $plagiarismplugins = plagiarism_load_available_plugins();
+    foreach($plagiarismplugins as $plugin => $dir) {
+        require_once($dir.'/lib.php');
+        $plagiarismclass = "plagiarism_plugin_$plugin";
+        $plagiarismplugin = new $plagiarismclass;
+        $plagiarismplugin->save_form_elements($data);
+    }
+}
+
+/**
+ * adds the list of plagiarism settings to a form - called inside modules that have enabled plagiarism
+ *
+ * @param object $mform - Moodle form object
+ * @param object $context - context object
+ */
+function plagiarism_get_form_elements_module($mform, $context) {
+    global $CFG;
+    if (empty($CFG->enableplagiarism)) {
+        return '';
+    }
+    $plagiarismplugins = plagiarism_load_available_plugins();
+    foreach($plagiarismplugins as $plugin => $dir) {
+        require_once($dir.'/lib.php');
+        $plagiarismclass = "plagiarism_plugin_$plugin";
+        $plagiarismplugin = new $plagiarismclass;
+        $plagiarismplugin->get_form_elements_module($mform, $context);
+    }
+}
+/**
+ * updates the status of all files within a module
+ *
+ * @param object $course - full Course object
+ * @param object $cm - full cm object
+ */
+function plagiarism_update_status($course, $cm) {
+    global $CFG;
+    if (empty($CFG->enableplagiarism)) {
+        return '';
+    }
+    $plagiarismplugins = plagiarism_load_available_plugins();
+    foreach($plagiarismplugins as $plugin => $dir) {
+        require_once($dir.'/lib.php');
+        $plagiarismclass = "plagiarism_plugin_$plugin";
+        $plagiarismplugin = new $plagiarismclass;
+        $plagiarismplugin->update_status($course, $cm);
+    }
+}
+
+/**
+* Function that prints the student disclosure notifying that the files will be checked for plagiarism
+* @param integer $cmid - the cmid of this module
+*/
+function plagiarism_print_disclosure($cmid) {
+    global $CFG;
+    if (empty($CFG->enableplagiarism)) {
+        return '';
+    }
+    $plagiarismplugins = plagiarism_load_available_plugins();
+    foreach($plagiarismplugins as $plugin => $dir) {
+        require_once($dir.'/lib.php');
+        $plagiarismclass = "plagiarism_plugin_$plugin";
+        $plagiarismplugin = new $plagiarismclass;
+        $plagiarismplugin->print_disclosure($cmid);
+    }
+}
+/**
+ * used by admin/cron.php to get similarity scores from submitted files.
+ *
+ */
+function plagiarism_cron() {
+    global $CFG;
+    if (empty($CFG->enableplagiarism)) {
+        return '';
+    }
+    $plagiarismplugins = plagiarism_load_available_plugins();
+    foreach($plagiarismplugins as $plugin => $dir) {
+        require_once($dir.'/lib.php');
+        $plagiarismclass = "plagiarism_plugin_$plugin";
+        $plagiarismplugin = new $plagiarismclass;
+        $plagiarismplugin->cron();
+    }
+}
+/** 
+ * helper function - also loads lib file of plagiarism plugin
+ * @return array of available plugins
+ */
+function plagiarism_load_available_plugins() {
+    global $CFG;
+    if (empty($CFG->enableplagiarism)) {
+        return array();
+    }
+    $plagiarismplugins = get_plugin_list('plagiarism');
+    $availableplugins = array();
+    foreach($plagiarismplugins as $plugin => $dir) {
+        //check this plugin is enabled and a lib file exists.
+        if (get_config('plagiarism', $plugin."_use") && file_exists($dir."/lib.php")) {
+            require_once($dir.'/lib.php');
+            $plagiarismclass = "plagiarism_plugin_$plugin";
+            if (class_exists($plagiarismclass)) {
+                $availableplugins[$plugin] = $dir;
+            }
+        }
+    }
+    return $availableplugins;
+}
diff --git a/mod/assignment/lib.php b/mod/assignment/lib.php
index 9600d73..0036192 100644
--- a/mod/assignment/lib.php
+++ b/mod/assignment/lib.php
@@ -207,6 +207,7 @@ class assignment_base {
         echo $OUTPUT->box_start('generalbox boxaligncenter', 'intro');
         echo format_module_intro('assignment', $this->assignment, $this->cm->id);
         echo $OUTPUT->box_end();
+        plagiarism_print_disclosure($this->cm->id);
     }
 
     /**
@@ -1026,6 +1027,7 @@ class assignment_base {
         /* first we check to see if the form has just been submitted
          * to request user_preference updates
          */
+        plagiarism_update_status($this->course, $this->cm);
         if (isset($_POST['updatepref'])){
             $perpage = optional_param('perpage', 10, PARAM_INT);
             $perpage = ($perpage <= 0) ? 10 : $perpage ;
@@ -1747,6 +1749,8 @@ class assignment_base {
                     $button->set_format_by_file($file);
                     $output .= $button->to_html(PORTFOLIO_ADD_ICON_LINK);
                 }
+                $output .= plagiarism_get_links(array('userid'=>$userid, 'file'=>$file, 'cmid'=>$this->cm->id, 'course'=>$this->course, 'assignment'=>$this->assignment));
+                $output .= '<br />';
             }
             if (count($files) > 1  && $this->portfolio_exportable() && has_capability('mod/assignment:exportownsubmission', $this->context)) {
                 $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id), '/mod/assignment/locallib.php');
diff --git a/mod/assignment/submissions.php b/mod/assignment/submissions.php
index ee0168e..2358465 100644
--- a/mod/assignment/submissions.php
+++ b/mod/assignment/submissions.php
@@ -2,6 +2,7 @@
 
 require_once("../../config.php");
 require_once("lib.php");
+require_once($CFG->libdir.'/plagiarismlib.php');
 
 $id   = optional_param('id', 0, PARAM_INT);          // Course module ID
 $a    = optional_param('a', 0, PARAM_INT);           // Assignment ID
diff --git a/mod/assignment/type/upload/assignment.class.php b/mod/assignment/type/upload/assignment.class.php
index bc1d760..dac6f97 100644
--- a/mod/assignment/type/upload/assignment.class.php
+++ b/mod/assignment/type/upload/assignment.class.php
@@ -296,6 +296,7 @@ class assignment_upload extends assignment_base {
                 $mimetype = $file->get_mimetype();
                 $path = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$this->context->id.'/mod_assignment/submission/'.$submission->id.'/'.$filename);
                 $output .= '<a href="'.$path.'" ><img class="icon" src="'.$OUTPUT->pix_url(file_mimetype_icon($mimetype)).'" alt="'.$mimetype.'" />'.s($filename).'</a>&nbsp;';
+                $output .= plagiarism_get_links(array('userid'=>$userid, 'file'=>$file, 'cmid'=>$this->cm->id, 'course'=>$this->course, 'assignment'=>$this->assignment));
             }
 
         }
@@ -361,6 +362,8 @@ class assignment_upload extends assignment_base {
                     $output .= '<a href="'.$delurl.'">&nbsp;'
                               .'<img title="'.$strdelete.'" src="'.$OUTPUT->pix_url('t/delete') . '" class="iconsmall" alt="" /></a> ';
                 }
+                $output .= plagiarism_get_links(array('userid'=>$userid, 'file'=>$file, 'cmid'=>$this->cm->id, 'course'=>$this->course, 'assignment'=>$this->assignment));
+                $output .= '<br />';
 
                 if (has_capability('mod/assignment:exportownsubmission', $this->context)) {
                     $button->set_callback_options('assignment_portfolio_caller', array('id' => $this->cm->id, 'fileid' => $file->get_id()), '/mod/assignment/locallib.php');
@@ -1065,6 +1068,8 @@ class assignment_upload extends assignment_base {
         $mform->addHelpButton('var4', 'trackdrafts', 'assignment');
         $mform->setDefault('var4', 1);
 
+        $course_context = get_context_instance(CONTEXT_COURSE, $COURSE->id);
+        plagiarism_get_form_elements_module($mform, $course_context);
     }
 
     function portfolio_exportable() {
diff --git a/mod/assignment/type/uploadsingle/assignment.class.php b/mod/assignment/type/uploadsingle/assignment.class.php
index 94539df..3f8b24d 100644
--- a/mod/assignment/type/uploadsingle/assignment.class.php
+++ b/mod/assignment/type/uploadsingle/assignment.class.php
@@ -23,6 +23,8 @@ class assignment_uploadsingle extends assignment_base {
                     $mimetype = $file->get_mimetype();
                     $path = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$this->context->id.'/mod_assignment/submission/'.$submission->id.'/'.$filename);
                     $output .= '<a href="'.$path.'" ><img class="icon" src="'.$OUTPUT->pix_url(file_mimetype_icon($mimetype)).'" alt="'.$mimetype.'" />'.s($filename).'</a><br />';
+                    $output .= plagiarism_get_links(array('userid'=>$userid, 'file'=>$file, 'cmid'=>$this->cm->id, 'course'=>$this->course, 'assignment'=>$this->assignment));
+                    $output .='<br/>';
                 }
             }
         }
@@ -153,6 +155,8 @@ class assignment_uploadsingle extends assignment_base {
         $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $choices);
         $mform->setDefault('maxbytes', $CFG->assignment_maxbytes);
 
+        $course_context = get_context_instance(CONTEXT_COURSE, $COURSE->id);
+        plagiarism_get_form_elements_module($mform, $course_context);
     }
 
     function portfolio_exportable() {
diff --git a/mod/assignment/view.php b/mod/assignment/view.php
index 3985143..2d80577 100644
--- a/mod/assignment/view.php
+++ b/mod/assignment/view.php
@@ -3,6 +3,7 @@
 require_once("../../config.php");
 require_once("lib.php");
 require_once($CFG->libdir . '/completionlib.php');
+require_once($CFG->libdir . '/plagiarismlib.php');
 
 $id = optional_param('id', 0, PARAM_INT);  // Course Module ID
 $a  = optional_param('a', 0, PARAM_INT);   // Assignment ID
diff --git a/plagiarism/lib.php b/plagiarism/lib.php
new file mode 100644
index 0000000..ea58f52
--- /dev/null
+++ b/plagiarism/lib.php
@@ -0,0 +1,76 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * lib.php - Contains Plagiarism base class used by plugins.
+ *
+ * @since 2.0
+ * @package    moodlecore
+ * @subpackage plagiarism
+ * @copyright  2010 Dan Marsden http://danmarsden.com
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+if (!defined('MOODLE_INTERNAL')) {
+    die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
+}
+
+//dummy class - all plugins should be based off this.
+class plagiarism_plugin {
+    /**
+     * hook to allow plagiarism specific information to be displayed beside a submission 
+     * @param array  $linkarraycontains all relevant information for the plugin to generate a link
+     * @return string
+     * 
+     */
+    public function get_links($linkarray) {
+        return '';
+    }
+    /**
+     * hook to add plagiarism specific settings to a module settings page
+     * @param object $mform  - Moodle form
+     * @param object $context - current context
+     */
+    public function get_form_elements_module($mform, $context) {
+    }
+    /* hook to save plagiarism specific settings on a module settings page
+     * @param object $data - data from an mform submission.
+     */
+    public function save_form_elements($data) {
+    }
+    /**
+     * hook to allow a disclosure to be printed notifying users what will happen with their submission
+     * @param int $cmid - course module id
+     * @return string
+     */
+    public function print_disclosure($cmid) {
+    }
+    /**
+     * hook to allow status of submitted files to be updated - called on grading/report pages.
+     *
+     * @param object $course - full Course object
+     * @param object $cm - full cm object
+     */
+    public function update_status($course, $cm) {
+    }
+    /**
+     * hook for cron
+     *
+     */
+    public function plagiarism_cron() {
+    }
+}
\ No newline at end of file
